<!-- ---
id: 关键字
title: 接口与别名的区别
--- -->


## keyof

作用： 获取类，对象，接口的所有** key ** 组成的 ** 联合类型**

```ts 
interface UserInfo {
    name: string,
    age: number
}

type UserInfoPlus = keyof UserInfo; 
// type UserInfoPlus = 'name' | 'age';


type ArrayMethods = keyof []; //  "pop" | "push" | "concat" | "join" ……

let a:ArrayMethods = 'push';


```

```ts 
function getUser<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}
```


## in
in 遍历操作。可以理解为 for ... in，表示从 keyof T 中去遍历每一个类型

```ts 


enum colors {
    RED, // 默认：RED = 0
    BLUE, // 默认：BLUE = 1
}

type ColorsMap = {
    [val in colors]: string;
}

// type ColorsMap = {
//     0: string;
//     1: string;
// }


type Optional<T> = { 
  [K in keyof T]?: T[K] 
};

const person: Optional<Person> = {
  name: "Tobias"
};

```

## infer

<!-- 占位符式的关键字

注意：学习该知识需要先学习泛型

表示在 extends 条件语句中以占位符出现的用来修饰数据类型的关键字，被修饰的数据类型等用到的时候才能被推断出来

作用： 获取参数，返回值，泛型 的类型

** 出现位置 ** 

- 参数
- 返回值
- 类型的泛型具体化类型上

例子1：出现位置在参数上

```ts 
interface Customer {
    custname: string
    buymoney: number
}

需求：获取custFuncType的参数类型
type custFuncType = (cust: Customer) => string

实现：
type inferType<T> = T extends (parmas: infer P) => any ? P : T

type inferReusltType = inferType<custFuncType>  //Customer类型



//详解
type inferType<T> = T extends (parmas: infer P) => any ? P : T

传递泛型后等于：
type inferType<custFuncType> = (cust: Customer) => string extends (parmas: infer P) => any ? P : (cust: Customer) => string

解释：
(cust: Customer) => string 的类型是否与 (parmas: infer P) => any 相同， 如果相同，返回P（这个P已经变成了Customer，这就是infer的作用，作为占位符使用）， 如果不同返回原来的表达式
在这个例子中，是相同的，因为any 是任何类型的子类或父类，肯定包括string， 所以返回P，也就是Customer
``` -->


## is
